import tkinter as tk
from tkinter import ttk, messagebox
import pyperclip
import pandas as pd
from ttkbootstrap import Style
import threading
import re
import os
from datetime import datetime


class IDSearchApp:
    def __init__(self, root):
        self.root = root
        self.root.title("身份证信息查询系统")
        self.root.geometry("500x400")

        # 设置窗口为弹窗性质（无最小化按钮）
        self.root.attributes('-toolwindow', True)
        self.root.attributes('-topmost', True)

        # 初始化关闭计数器
        self.close_count = 0

        # 修改窗口协议，重写关闭行为
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)

        # 初始化日志系统
        self.log_file = "id_search_log.txt"
        self.init_log_file()

        # 应用样式
        self.style = Style(theme='flatly')

        # 数据文件路径
        self.excel_path = self.get_latest_excel_file()

        # 初始化变量
        self.df = None
        self.data_loaded = False
        self.last_clipboard_content = ""

        # 创建界面
        self.create_widgets()

        # 加载数据
        self.load_data_thread()

        # 启动剪贴板监控
        self.start_clipboard_monitor()

    def on_close(self):
        """处理窗口关闭事件"""
        self.close_count += 1

        # 如果是第一次点击，设置2秒后重置的定时器
        if self.close_count == 1:
            self.reset_timer = self.root.after(2000, self.reset_close_count)

        remaining = 3 - self.close_count

        if self.close_count >= 3:
            # 取消可能存在的重置定时器
            if hasattr(self, 'reset_timer'):
                self.root.after_cancel(self.reset_timer)
            self.write_log("系统操作", "程序退出")
            self.clipboard_monitor_active = False
            self.root.destroy()
        else:
            self.status_var.set(f"再点击 {remaining} 次关闭按钮将退出程序")
            self.write_log("用户操作", f"尝试关闭程序 ({self.close_count}/3)")

    def reset_close_count(self):
        """重置关闭计数器"""
        if self.close_count < 3:  # 只有未达到3次时才重置
            self.close_count = 0
            self.status_var.set("就绪")
            self.write_log("系统操作", "关闭计数器已重置")

    def init_log_file(self):
        """初始化日志文件"""
        if not os.path.exists(self.log_file):
            with open(self.log_file, "w", encoding="utf-8") as f:
                f.write("身份证查询系统日志\n")
                f.write("=" * 50 + "\n")

    def write_log(self, action, content, result=""):
        """写入日志文件"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] {action}: {content}"
        if result:
            log_entry += f" | 结果: {result}"
        log_entry += "\n"

        with open(self.log_file, "a", encoding="utf-8") as f:
            f.write(log_entry)

        # 在状态栏显示最新日志
        self.status_var.set(log_entry.strip())

    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 顶部标题和按钮
        header_frame = ttk.Frame(main_frame)
        header_frame.pack(fill=tk.X, pady=(0, 10))

        ttk.Label(
            header_frame,
            text="身份证信息查询系统",
            font=('Helvetica', 16, 'bold')
        ).pack(side=tk.LEFT)

        # 右侧按钮框架
        btn_frame = ttk.Frame(header_frame)
        btn_frame.pack(side=tk.RIGHT)

        # 修改"确定"按钮功能 - 改为最小化窗口
        ttk.Button(
            btn_frame,
            text="确定",
            command=self.minimize_window,  # 改为最小化窗口
            style='info.Outline.TButton',
            width=8
        ).pack(side=tk.LEFT, padx=2)

        # 日志按钮
        ttk.Button(
            btn_frame,
            text="查看日志",
            command=self.view_logs,
            style='info.Outline.TButton',
            width=8
        ).pack(side=tk.LEFT, padx=2)

        # 搜索控制区
        control_frame = ttk.LabelFrame(
            main_frame,
            text="查询控制",
            padding=(15, 10)
        )
        control_frame.pack(fill=tk.X, pady=5)

        # 搜索输入框
        search_frame = ttk.Frame(control_frame)
        search_frame.pack(fill=tk.X, pady=5)

        ttk.Label(search_frame, text="身份证号:").pack(side=tk.LEFT)
        self.search_entry = ttk.Entry(search_frame, width=30)
        self.search_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)

        # 操作按钮
        btn_frame = ttk.Frame(search_frame)
        btn_frame.pack(side=tk.LEFT, padx=5)

        ttk.Button(
            btn_frame,
            text="查询",
            command=self.search_id,
            style='success.TButton',
            width=8
        ).pack(side=tk.LEFT, padx=2)

        ttk.Button(
            btn_frame,
            text="清空",
            command=self.clear_search,
            style='danger.TButton',
            width=8
        ).pack(side=tk.LEFT, padx=2)

        # 结果显示区
        result_frame = ttk.LabelFrame(
            main_frame,
            text="查询结果",
            padding=10
        )
        result_frame.pack(fill=tk.BOTH, expand=True)

        # 文本显示区域
        self.result_text = tk.Text(
            result_frame,
            wrap=tk.WORD,
            font=('Microsoft YaHei', 11),
            padx=10,
            pady=10,
            height=8,
            state=tk.DISABLED
        )
        self.result_text.pack(fill=tk.BOTH, expand=True)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("系统就绪")
        status_bar = ttk.Label(
            main_frame,
            textvariable=self.status_var,
            relief=tk.SUNKEN,
            anchor=tk.W,
            padding=(10, 5, 10, 5),
            font=('Microsoft YaHei', 9),
            style='secondary.TLabel'
        )
        status_bar.pack(fill=tk.X, pady=(5, 0))

        # 绑定回车键
        self.search_entry.bind('<Return>', lambda e: self.search_id())

    def minimize_window(self):
        """最小化窗口（隐藏窗口）"""
        self.root.withdraw()  # 隐藏窗口
        self.write_log("用户操作", "窗口隐藏")

    def restore_window(self):
        """恢复窗口（显示窗口）"""
        if not self.root.winfo_viewable():  # 如果窗口不可见
            self.root.deiconify()  # 显示窗口
            self.root.attributes('-topmost', True)  # 重新置顶
            self.write_log("系统操作", "窗口已恢复")

    def view_logs(self):
        """查看日志内容"""
        try:
            with open(self.log_file, "r", encoding="utf-8") as f:
                logs = f.read()

            # 创建日志查看窗口
            log_window = tk.Toplevel(self.root)
            log_window.title("查询日志")
            log_window.geometry("800x600")
            log_window.attributes('-topmost', True)  # 日志窗口也置顶

            # 添加文本控件显示日志
            text_frame = ttk.Frame(log_window)
            text_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

            log_text = tk.Text(
                text_frame,
                wrap=tk.WORD,
                font=('Courier New', 10)
            )
            log_text.pack(fill=tk.BOTH, expand=True)
            log_text.insert(tk.END, logs)
            log_text.config(state=tk.DISABLED)

            # 添加关闭按钮
            btn_frame = ttk.Frame(log_window)
            btn_frame.pack(fill=tk.X, padx=10, pady=(0, 10))

            ttk.Button(
                btn_frame,
                text="关闭",
                command=log_window.destroy,
                style='danger.TButton'
            ).pack(side=tk.RIGHT)

        except Exception as e:
            messagebox.showerror("错误", f"无法读取日志文件: {str(e)}")

    def start_clipboard_monitor(self):
        """启动剪贴板监控"""
        self.clipboard_monitor_active = True
        self.monitor_clipboard()

    def monitor_clipboard(self):
        """持续监控剪贴板内容"""
        if not hasattr(self, 'clipboard_monitor_active') or not self.clipboard_monitor_active:
            return

        try:
            current_content = pyperclip.paste().strip()

            # 检查是否是新的身份证号
            if (current_content != self.last_clipboard_content and
                    self.is_valid_id_number(current_content)):
                # 恢复窗口
                self.restore_window()

                # 更新界面
                self.search_entry.delete(0, tk.END)
                self.search_entry.insert(0, current_content)

                # 记录日志
                self.write_log("剪贴板检测到身份证号", current_content[:6] + "..." + current_content[-4:])

                # 执行查询
                self.search_id()

                # 更新最后记录的内容
                self.last_clipboard_content = current_content

        except Exception as e:
            print(f"剪贴板监控错误: {e}")

        # 每0.3秒检查一次剪贴板
        self.root.after(300, self.monitor_clipboard)

    def get_latest_excel_file(self):
        current_dir = os.getcwd()
        xlsx_files = [f for f in os.listdir(current_dir) if f.endswith('.xlsx')]

        if xlsx_files:
            # 假设选择第一个 .xlsx 文件作为目标
            return os.path.join(current_dir, xlsx_files[0])
        else:
            raise FileNotFoundError("未找到任何 .xlsx 文件")

    def is_valid_id_number(self, text):
        """验证是否为有效的身份证号格式"""
        # 简单的身份证号格式验证
        pattern = r'^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$'
        return re.match(pattern, text) is not None

    def load_data_thread(self):
        """后台线程加载数据"""
        self.status_var.set("正在加载数据文件...")
        self.write_log("系统操作", "开始加载数据文件")
        threading.Thread(target=self.load_data, daemon=True).start()

    def load_data(self):
        """加载Excel数据"""
        try:
            self.df = pd.read_excel(self.excel_path)

            # 预处理数据
            if '证件号码' in self.df.columns:
                # 去除空白字符
                self.df['证件号码'] = self.df['证件号码'].astype(str).str.strip()
                # 设为索引提高查询速度
                self.df.set_index('证件号码', inplace=True, drop=False)

            self.data_loaded = True
            msg = f"数据加载完成 | 共 {len(self.df)} 条记录"
            self.root.after(0, lambda: self.status_var.set(msg))
            self.write_log("系统操作", msg)
        except Exception as e:
            error_msg = f"加载数据失败: {str(e)}"
            self.root.after(0, lambda: messagebox.showerror("错误", error_msg))
            self.root.after(0, lambda: self.status_var.set(error_msg))
            self.write_log("系统错误", error_msg)

    def clear_search(self):
        """清空搜索条件和结果"""
        self.search_entry.delete(0, tk.END)
        self.result_text.config(state=tk.NORMAL)
        self.result_text.delete(1.0, tk.END)
        self.result_text.config(state=tk.DISABLED)
        self.status_var.set("已清空搜索条件")
        self.write_log("用户操作", "清空搜索条件")

    def search_id(self):
        """执行身份证号查询"""
        if not self.data_loaded:
            messagebox.showwarning("警告", "数据尚未加载完成，请稍后再试")
            return

        id_number = self.search_entry.get().strip()
        if not id_number:
            messagebox.showerror("错误", "请输入身份证号")
            return

        # 验证身份证号格式
        if not self.is_valid_id_number(id_number):
            error_msg = "无效的身份证号格式"
            messagebox.showerror("错误", error_msg)
            self.write_log("查询错误", id_number[:6] + "..." + id_number[-4:], error_msg)
            return

        # 更新状态
        self.status_var.set(f"正在查询: {id_number[:6]}...{id_number[-4:]}")
        self.root.update_idletasks()

        try:
            # 清空现有结果
            self.result_text.config(state=tk.NORMAL)
            self.result_text.delete(1.0, tk.END)

            # 执行查询
            if id_number in self.df.index:
                result = self.df.loc[[id_number]]

                # 显示结果到文本区域
                for _, row in result.iterrows():
                    display_text = ""
                    for col_name, value in row.items():
                        # 跳过空值
                        if pd.isna(value):
                            continue
                        # 身份证号特殊处理
                        if '证件号码' in col_name or '身份证' in col_name:
                            display_text += f"{col_name}: {value}\n"
                        else:
                            display_text += f"{col_name}: {value}\n"

                    self.result_text.insert(tk.END, display_text + "\n")
                    self.result_text.see(tk.END)  # 滚动到底部

                    # 记录日志（保持用"|"分隔）
                    log_data = " | ".join([str(x) if pd.notna(x) else "" for x in row.values])
                    success_msg = f"查询结果: {log_data}"
                    self.status_var.set("查询成功")
                    self.write_log("查询成功", id_number[:6] + "..." + id_number[-4:], success_msg)
            else:
                not_found_msg = "未找到匹配记录"
                self.result_text.insert(tk.END, not_found_msg + "\n")
                self.status_var.set(f"未找到身份证号: {id_number[:6]}...{id_number[-4:]}")
                messagebox.showinfo("结果", not_found_msg)
                self.write_log("查询结果", id_number[:6] + "..." + id_number[-4:], not_found_msg)

            self.result_text.config(state=tk.DISABLED)

        except Exception as e:
            error_msg = f"查询失败: {str(e)}"
            messagebox.showerror("错误", error_msg)
            self.status_var.set(f"查询出错: {str(e)}")
            self.write_log("查询错误", id_number[:6] + "..." + id_number[-4:], error_msg)



if __name__ == "__main__":
    root = tk.Tk()
    app = IDSearchApp(root)
    root.mainloop()